home *** CD-ROM | disk | FTP | other *** search
/ Mac Magazin/MacEasy 11 / Mac Magazin and MacEasy Magazine CD - Issue 11.iso / Sharewarebibliothek / Entwickler / WASTE 1.1 C / WEScraps.c < prev    next >
Text File  |  1995-04-29  |  12KB  |  416 lines

  1. // { WASTE PROJECT: }
  2. // { Routines for manipulating style scraps and object soups }
  3.  
  4. // { Copyright © 1993-1994 Marco Piovanelli }
  5. // { All Rights Reserved }
  6.  
  7. #include "WASTEIntf.h"
  8.  
  9. pascal OSErr _WEPrependStyle(Handle hStyleScrap, WERunInfo *info, long offsetDelta)
  10. {
  11.     // { compare the stylistic attributes in info with the first element of the specified }
  12.     // { style scrap: if they differ, prepend a new element to the style scrap. }
  13.     // { in any case, advance all character offsets in the style scrap by offsetDelta }
  14.  
  15.     TEStyleScrapPtr pScrap;
  16.     Size scrapSize;
  17.     short i;
  18.     OSErr err;
  19.  
  20.     pScrap = *(TEStyleScrapHandle)hStyleScrap;
  21.  
  22.     // { compare this style info with that stored in the first element of our private style scrap }
  23.     if (_WEBlockCmp((Ptr)&pScrap->scrpStyleTab[0].scrpTEAttrs, (Ptr)&info->runAttrs,
  24.          sizeof(TERunAttributes))
  25.          == false) 
  26.     {
  27.  
  28.         // { leng the style scrap }
  29.         scrapSize = GetHandleSize(hStyleScrap);
  30.         SetHandleSize(hStyleScrap, scrapSize + sizeof(TEStyleScrapElement));
  31.         err = MemError();
  32.         if (err != noErr) 
  33.             return err;
  34.  
  35.         // { move old contents forward }
  36.         pScrap = *(TEStyleScrapHandle)hStyleScrap;
  37.         BlockMoveData(&pScrap->scrpStyleTab[0], &pScrap->scrpStyleTab[1], scrapSize - sizeof(short));
  38.  
  39.         // { insert a new element at the beginning }
  40.         pScrap->scrpStyleTab[0].scrpStartChar = 0;
  41.         pScrap->scrpStyleTab[0].scrpTEAttrs = *(TERunAttributes *)&info->runAttrs;
  42.  
  43.         // { increment scrap counter }
  44.         pScrap->scrpNStyles = pScrap->scrpNStyles + 1;
  45.  
  46.     } // { if not _WEBlockCmp }
  47.  
  48.     // { update char offsets within the style scrap }
  49.     for(i = pScrap->scrpNStyles - 1; i>0; i--)
  50.     {
  51.         pScrap->scrpStyleTab[i].scrpStartChar = pScrap->scrpStyleTab[i].scrpStartChar + offsetDelta;
  52.     }
  53.  
  54.     // { return result code }
  55.     return noErr;
  56. } // { _WEPrependStyle }
  57.  
  58. pascal OSErr _WEAppendStyle(Handle hStyleScrap, WERunInfo *info, long offset)
  59. {
  60.  
  61.     // { compare the stylistic attributes in info with the last element of the specified }
  62.     // { style scrap: if they differ, append a new element to the style scrap. }
  63.  
  64.     TEStyleScrapPtr pScrap;
  65.     TEStyleScrapElement element;
  66.     OSErr err;
  67.  
  68.     pScrap = *(TEStyleScrapHandle)hStyleScrap;
  69.     // { compare this style info with that stored in the first element of our private style scrap }
  70.     if (_WEBlockCmp((Ptr)&pScrap->scrpStyleTab[pScrap->scrpNStyles - 1].scrpTEAttrs,
  71.         (Ptr)&info->runAttrs, sizeof(TERunAttributes)) == false) 
  72.     {
  73.  
  74.         // { create a new style scrap element }
  75.         element.scrpStartChar = offset;
  76.         element.scrpTEAttrs = *(TERunAttributes *)&info->runAttrs;
  77.  
  78.         // { append it at the end of the style scrap }
  79.         err = PtrAndHand(&element, hStyleScrap, sizeof(element));
  80.         err = MemError();
  81.         if (err != noErr)
  82.             return err;
  83.  
  84.         // { increment scrap counter }
  85.         pScrap = *(TEStyleScrapHandle)hStyleScrap;
  86.         pScrap->scrpNStyles = pScrap->scrpNStyles + 1;
  87.  
  88.     } // { if not _WEBlockCmp }
  89.  
  90.     // { return result code }
  91.     return noErr;
  92. } // { _WEAppendStyle }
  93.  
  94.  
  95. pascal OSErr _WEPrependObject(Handle hSoup, WERunInfo *info, long offsetDelta)
  96. {
  97.     // { if info describes an embedded object, prepend a new object descriptor, }
  98.     // { complete with the associated object data, to the specified soup. }
  99.     // { in any case, advance all character offsets in the soup by offsetDelta }
  100.  
  101.     WEObjectDescPtr pDesc;
  102.     WESoupPtr pSoup;
  103.     Size soupSize, objectDataSize, extraSize;
  104.     OSErr err;
  105.  
  106.     // { get size of existing soup }
  107.     soupSize = GetHandleSize(hSoup);
  108.  
  109.     // { extract object descriptor handle from WERunInfo record }
  110.     // { if hObject is non-NIL, info describes an embedded object }
  111.     if (info->runAttrs.runStyle.tsObject != kNullObject) 
  112.     {
  113.         pDesc = *(WEObjectDescHandle)(info->runAttrs.runStyle.tsObject);
  114.  
  115.         // { get size of object data }
  116.         objectDataSize = GetHandleSize(pDesc->objectDataHandle);
  117.  
  118.         // { extra size to add to existing soup is descriptor size + object data size }
  119.         extraSize = sizeof(WESoup) + objectDataSize;
  120.  
  121.         // { resize the soup }
  122.         SetHandleSize(hSoup, soupSize + extraSize);
  123.         err = MemError();
  124.         if (err != noErr)
  125.             return err;
  126.  
  127.         // { move old contents forward }
  128.         pSoup = *(WESoupHandle)hSoup;
  129.         BlockMoveData((Ptr)pSoup, (Ptr)pSoup + extraSize, soupSize);
  130.  
  131.         // { insert the new object descriptor at the beginning }
  132.         _WEBlockClr((Ptr)pSoup, sizeof(WESoup));
  133.         pDesc = *(WEObjectDescHandle)(info->runAttrs.runStyle.tsObject);
  134.         pSoup->soupType = pDesc->objectType;
  135.         pSoup->soupSize = pDesc->objectSize;
  136.         pSoup->soupDataSize = objectDataSize;
  137.  
  138.         // {  copy the object data }
  139.         BlockMoveData(*pDesc->objectDataHandle, (Ptr)pSoup + sizeof(WESoup), objectDataSize);
  140.     }
  141.     else
  142.     {
  143.         pSoup = *(WESoupHandle)hSoup;
  144.         extraSize = 0;
  145.     }
  146.  
  147.     // { update char offsets within the soup }
  148.     while (soupSize > 0)
  149.     {
  150.         pSoup = (WESoupPtr)((Ptr)pSoup + extraSize);
  151.         pSoup->soupOffset = pSoup->soupOffset + offsetDelta;
  152.         extraSize = pSoup->soupDataSize + sizeof(WESoup);
  153.         soupSize = soupSize - extraSize;
  154.     }
  155.  
  156.     return noErr;
  157. } // { _WEPrependObject }
  158.  
  159. pascal OSErr _WEAppendObject(Handle hSoup, WERunInfo *info, long offset)
  160. {
  161.  
  162.     // { if info describes an embedded object, append a new object descriptor, }
  163.     // { complete with the associated object data, to the specified soup. }
  164.  
  165.     WEObjectDescPtr pDesc;
  166.     Handle hObjectData;
  167.     WESoup soupItem;
  168.     Boolean saveDataLock;
  169.     OSErr err;
  170.  
  171.     if (info->runAttrs.runStyle.tsObject != kNullObject)
  172.     {
  173.         pDesc = *(WEObjectDescHandle)info->runAttrs.runStyle.tsObject;
  174.         hObjectData = pDesc->objectDataHandle;
  175.  
  176.         // { fill in a soup item }
  177.         _WEBlockClr((Ptr)&soupItem, sizeof(soupItem));
  178.         soupItem.soupOffset = offset;
  179.         soupItem.soupType = pDesc->objectType;
  180.         soupItem.soupSize = pDesc->objectSize;
  181.         soupItem.soupDataSize = GetHandleSize(hObjectData);
  182.  
  183.         // { append it to the soup handle }
  184.         PtrAndHand(&soupItem, hSoup, sizeof(soupItem));
  185.         err = MemError();
  186.         if (err != noErr) return err;
  187.  
  188.         // { append the actual object data to the soup handle }
  189.         saveDataLock = _WESetHandleLock(hObjectData, true);
  190.         PtrAndHand(*hObjectData, hSoup, soupItem.soupDataSize);
  191.         err = MemError();
  192.         _WESetHandleLock(hObjectData, saveDataLock);
  193.         if (err != noErr) return err;
  194.     } // { if object reference is not NIL }
  195.  
  196.     // { clear result code }
  197.     return noErr;
  198. } // { _WEAppendObject }
  199.  
  200. pascal OSErr WECopyRange(long rangeStart, long rangeEnd, Handle hText, Handle
  201.                     hStyles, Handle hSoup, WEHandle hWE)
  202. {
  203.  
  204.     // { Make a copy of the specified range of text: store the characters in hText }
  205.     // { and the associated style scrap in hStyles.  The handles are resized as necessary. }
  206.     // { Specify NIL in hText or hStyles if you don't want the corresponding info returned. }
  207.  
  208.     WEPtr pWE;
  209.     long rangeLength;
  210.     long firstRun, nRuns, i;
  211.     long startChar;
  212.     WERunInfo info;
  213.     short *pElement;
  214.     Boolean saveWELock;
  215.     OSErr err;
  216.     TEStyleScrapElementPtr pElem2;
  217.  
  218.     // { lock the WE record }
  219.     saveWELock = _WESetHandleLock((Handle)hWE, true);
  220.     pWE = *hWE;
  221.  
  222.     // { range-check parameters and reorder them if necessary }
  223.     rangeStart = _WEPinInRange(rangeStart, 0, pWE->textLength);
  224.     rangeEnd = _WEPinInRange(rangeEnd, 0, pWE->textLength);
  225.     _WEReorder(&rangeStart, &rangeEnd);
  226.     rangeLength = rangeEnd - rangeStart;
  227.  
  228.     if (hText != nil) 
  229.     {
  230.         // { resize the given handle }
  231.         SetHandleSize(hText, rangeLength);
  232.         err = MemError();
  233.         if (err != noErr) 
  234.         {
  235.             goto cleanup;
  236.         }
  237.  
  238.         // { copy the text range }
  239.         BlockMoveData((Ptr)*pWE->hText + rangeStart, (Ptr)*hText, rangeLength);
  240.  
  241.     }
  242.  
  243.     // { make the soup handle zero-length }
  244.     if (hSoup != nil)
  245.     {
  246.         SetHandleSize(hSoup, 0);
  247.         err = MemError();
  248.         if (err != noErr)
  249.                 goto cleanup;
  250.     }
  251.  
  252.     if (hStyles != nil || hSoup != nil) 
  253.     {
  254.         // { count how many style runs there are in the selection range }
  255.         firstRun = _WEOffsetToRun(rangeStart, hWE);
  256.         nRuns = _WEOffsetToRun(rangeEnd - 1, hWE) - firstRun + 1;
  257.  
  258.         if (hStyles != nil)
  259.         {
  260.             // { resize the given style scrap handle and lock it in high heap }
  261.             SetHandleSize((Handle)hStyles, (((long)nRuns) * sizeof(ScrpSTElement)) + 2);
  262.             err = MemError();
  263.             if (err != noErr)
  264.                 goto cleanup;
  265.             HLockHi((Handle)hStyles);
  266.             pElement = (short *)*hStyles;
  267.             
  268.             // { fill in the style count in the style scrap }
  269.             // { *** POTENTIAL PROBLEM: if nRuns > 32767, scrpNStyles will be invalid *** }
  270.             *pElement = nRuns;
  271.             pElement++;
  272.         }
  273.         
  274.         pElem2 = (TEStyleScrapElementPtr)pElement;
  275.         // { loop through every style run in the selection range }
  276.         for(i = 0; i<nRuns; i++)
  277.         {
  278.             _WEGetIndStyle(firstRun + i, &info, hWE);
  279.             
  280.             // { calculate the start character for this style run, relative to the beginning of the range }
  281.             startChar = info.runStart - rangeStart;
  282.             if (startChar < 0)
  283.             {
  284.                 startChar = 0;
  285.                 info.runAttrs.runStyle.tsObject = kNullObject;
  286.             }
  287.             if (hStyles != nil)
  288.             {
  289.                 info.runAttrs.runStyle.tsFlags = 0; // { don't export internal flags }
  290.                 pElem2->scrpStartChar = startChar;
  291.                 pElem2->scrpTEAttrs = *(TERunAttributes *)&info.runAttrs;
  292.                 pElem2++;
  293.             }
  294.             if (hSoup != nil)
  295.             {
  296.                 // { if this style run references an embedded object, append it to the "soup" }
  297.                 if (info.runAttrs.runStyle.tsObject != kNullObject)
  298.                 {
  299.                     err = _WEAppendObject(hSoup, &info, startChar);
  300.                     if (err != noErr)
  301.                         goto cleanup;
  302.                 }
  303.             }
  304.         }
  305.     }
  306.     // { clear result code }
  307.     err = noErr;
  308.  
  309. cleanup:
  310.     
  311.     // { unlock the style scrap handle }
  312.     if (hStyles != nil)
  313.         HUnlock((Handle)hStyles);
  314.  
  315.     // { unlock the WE record }
  316.     _WESetHandleLock((Handle)hWE, saveWELock);
  317.     // { return result code }
  318.     return err;
  319. }
  320.  
  321. pascal OSErr WECopy(WEHandle hWE)
  322. {
  323.     // { Copy the selection range to the desk scrap }
  324.  
  325.     WEPtr pWE;
  326.     AEDesc d[3];
  327.     WEObjectDescHandle hObjectDesc;
  328.     Handle hItem;
  329.     Size itemSize;
  330.     short i, numTypes;
  331.     Boolean saveWELock, saveDataLock;
  332.     Boolean disposeData;
  333.     OSErr err;
  334.  
  335.     d[0].dataHandle = nil;
  336.     d[1].dataHandle = nil;
  337.     d[2].dataHandle = nil;
  338.     disposeData = false;
  339.  
  340.     // { lock the WE record }
  341.     saveWELock = _WESetHandleLock((Handle)hWE, true);
  342.     pWE = *hWE;
  343.  
  344.     // { return weEmptySelectionErr if the selection range is empty }
  345.     if (pWE->selStart == pWE->selEnd)
  346.     {
  347.         err = weEmptySelectionErr;
  348.         goto cleanup;
  349.     }
  350.     
  351.     // { clear the desk scrap }
  352.     err = ZeroScrap();
  353.     if (err != noErr)
  354.         goto cleanup;
  355.  
  356.     // { if the selection range consists of an embedded object, copy that }
  357.     if (WEGetSelectedObject(&hObjectDesc, hWE) == noErr)
  358.     {
  359.         d[0] = **(AEDesc **)(hObjectDesc);
  360.         numTypes = 1;
  361.     }
  362.     else
  363.     {
  364.         // { allocate three zero-length handles to hold the text, the styles and the "soup" }
  365.         for (i=0; i<3; i++)
  366.         {
  367.             err = _WEAllocate(0, kAllocTemp, &d[i].dataHandle);
  368.             if (err != noErr)
  369.                 goto cleanup;
  370.         }
  371.  
  372.         // { make a copy of the selection text and styles and create an object "soup" }
  373.         err = WECopyRange(pWE->selStart, pWE->selEnd, d[0].dataHandle,
  374.                 d[1].dataHandle, d[2].dataHandle, hWE);
  375.         if (err != noErr)
  376.             goto cleanup;
  377.         
  378.         // { tag the data }
  379.         d[0].descriptorType = kTypeText;
  380.         d[1].descriptorType = kTypeStyles;
  381.         d[2].descriptorType = kTypeSoup;
  382.         numTypes = 3;
  383.         disposeData = true;
  384.     }
  385.     
  386.     // { copy the items to the desk scrap }
  387.     for (i= 0; i<numTypes; i++)
  388.     {
  389.         hItem = d[i].dataHandle;
  390.         itemSize = GetHandleSize(hItem);
  391.         if (itemSize > 0)
  392.         {
  393.             saveDataLock = _WESetHandleLock(hItem, true);
  394.             err = PutScrap(itemSize, d[i].descriptorType, *hItem);
  395.             _WESetHandleLock(hItem, saveDataLock);
  396.             if (err != noErr)
  397.                 goto cleanup;
  398.         }
  399.     }
  400.  
  401.     // { clear result code }
  402.     err = noErr;
  403.  
  404. cleanup:
  405.     // { clean up }
  406.     if (disposeData)
  407.     {
  408.         _WEForgetHandle(&d[0].dataHandle);
  409.         _WEForgetHandle(&d[1].dataHandle);
  410.         _WEForgetHandle(&d[2].dataHandle);
  411.     }
  412.     _WESetHandleLock((Handle)hWE, saveWELock);
  413.     return err;
  414. }
  415.  
  416.